/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/* Generated By:JJTree: Do not edit this line. SimpleNode.java */

// package org.apache.el.parser;
package com.gdevelop.gwtxp.rebind.el;


import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;

/**
 * @author Jacob Hookom [jacob@hookom.net]
 * @version $Change: 181177 $$DateTime: 2001/06/26 08:45:09 $$Author: markt $
 */
public abstract class SimpleNode implements Node {
    protected Node parent;

    protected Node[] children;

    protected int id;

    protected String image;

    public SimpleNode(int i) {
        id = i;
    }

    public void jjtOpen() {
    }

    public void jjtClose() {
    }

    public void jjtSetParent(Node n) {
        parent = n;
    }

    public Node jjtGetParent() {
        return parent;
    }

    public void jjtAddChild(Node n, int i) {
        if (children == null) {
            children = new Node[i + 1];
        } else if (i >= children.length) {
            Node c[] = new Node[i + 1];
            System.arraycopy(children, 0, c, 0, children.length);
            children = c;
        }
        children[i] = n;
    }

    public Node jjtGetChild(int i) {
        return children[i];
    }

    public int jjtGetNumChildren() {
        return (children == null) ? 0 : children.length;
    }

    /*
     * You can override these two methods in subclasses of SimpleNode to
     * customize the way the node appears when the tree is dumped. If your
     * output uses more than one line you should override toString(String),
     * otherwise overriding toString() is probably all you need to do.
     */

    public String toString() {
        if (this.image != null) {
            return ELParserTreeConstants.jjtNodeName[id] + "[" + this.image
                    + "]";
        }
        return ELParserTreeConstants.jjtNodeName[id];
    }

    public String toString(String prefix) {
        return prefix + toString();
    }

    /*
     * Override this method if you want to customize how the node dumps out its
     * children.
     */

    public void dump(String prefix) {
        System.out.println(toString(prefix));
        if (children != null) {
            for (int i = 0; i < children.length; ++i) {
                SimpleNode n = (SimpleNode) children[i];
                if (n != null) {
                    n.dump(prefix + " ");
                }
            }
        }
    }

    public String getImage() {
        return image;
    }

    public void setImage(String image) {
        this.image = image;
    }

    public void accept(NodeVisitor visitor) throws Exception {
        visitor.visit(this);
        if (this.children != null && this.children.length > 0) {
            for (int i = 0; i < this.children.length; i++) {
                this.children[i].accept(visitor);
            }
        }
    }

  //a: Trung
  /**
   * @see ELParserTreeConstants
   */
  public static final String[] operators = {
    "??"
    , "??"
    , "??"
    , "??"
    , "??"
    , "??"      // JJTCHOICE = 5;
    , "||"      // JJTOR = 6;
    , "&&"      // JJTAND = 7;
    , "=="      // JJTEQUAL = 8;
    , "!="      // JJTNOTEQUAL = 9;
    , "<"       // JJTLESSTHAN = 10;
    , ">"       // JJTGREATERTHAN = 11;
    , "<="      // JJTLESSTHANEQUAL = 12;
    , ">="      // JJTGREATERTHANEQUAL = 13;
    , "+"       // JJTPLUS = 14;
    , "-"       // JJTMINUS = 15;
    , "*"       // JJTMULT = 16;
    , "/"       // JJTDIV = 17;
    , "%"       // JJTMOD = 18;
    , "-"       // JJTNEGATIVE = 19;
    , "!"       // JJTNOT = 20;
    , "??"
    , "??"
    , "??"
    , "??"
    , "??"
    , "??"
    , "??"
  };
  
  public JClassType getReturnType(ELParserContext ctx) throws ELException, NotFoundException{
    System.out.println("WARN: " + this.getClass() + " should overwrite getReturnType method");
    
    return ctx.getTypeOracle().getType(Object.class.getName());
  }

  public boolean isStaticValue(ELParserContext ctx) throws ELException, NotFoundException{
    System.out.println("WARN: " + this.getClass() + " should overwrite isStaticValue method");

    if (this.children != null){
      for (Node child : this.children){
        if (!child.isStaticValue(ctx)){
          return false;
        }
      }
    }
    return true;
  }
  
  public boolean isSimpleExpression(ELParserContext ctx) throws ELException, NotFoundException{
    System.out.println("WARN: " + this.getClass() + " should overwrite isStaticValue method");
    
    return false;
  }

  public String generateModelObservaleValue(ELParserContext ctx) throws ELException, NotFoundException {
    System.out.println("WARN: " + this.getClass() + " should overwrite generateModelObservaleValue method");
    
    return "";
  }
  
  public String generateGetExpressionWithConversion(ELParserContext ctx, JClassType toType) throws ELException, NotFoundException{
    StringBuffer buffer = new StringBuffer();
    JClassType fromType = this.getReturnType(ctx);
    if (fromType != toType){
      buffer.append("(" + toType.getName() + ")Converters.getConverter(" + fromType.getName() + ".class, " + toType.getName() + ".class).convert(");
    }
    buffer.append(generateGetExpression(ctx));
    if (fromType != toType){
      buffer.append(")");
    }
    
    return buffer.toString();
  }
  public String generateGetExpression(ELParserContext ctx) throws ELException, NotFoundException{
    System.out.println("WARN: " + this.getClass() + " should overwrite generateGetExpression method");
    
    return "";
  }
  
  public String generateMethodBinding(ELParserContext ctx) throws ELException, NotFoundException{
    System.out.println("WARN: " + this.getClass() + " should overwrite generateMethodBinding method");
    
    return "";
  }
  
  /**
   * Generate ComputedValue for ONE operand expression
   * @param ctx
   * @param id
   * @param child0
   * @param valueType
   * @return
   * @throws ELException
   * @throws NotFoundException
   */
  protected String generateComputedValue1(ELParserContext ctx, int id, Node child0, JClassType valueType) throws ELException, NotFoundException{
    StringBuffer sb = new StringBuffer();
    
    sb.append("new ComputedValue(" + valueType.getQualifiedSourceName() + ".class){\n");
    if (!child0.isStaticValue(ctx)){
      sb.append("  IObservableValue v0 = ");
      sb.append(child0.generateModelObservaleValue(ctx));
      sb.append(";\n");
    }
    
    sb.append("  protected Object calculate(){\n");
    
    sb.append("    return ");
    sb.append(" "); sb.append(operators[this.id]); sb.append(" ");
    if (!child0.isStaticValue(ctx)){
      sb.append("(");
      sb.append(child0.getReturnType(ctx).getQualifiedSourceName());
      sb.append(")v0.getValue()");
    }else{
      sb.append(child0.generateGetExpression(ctx));
    }
    sb.append(";\n");

    sb.append("  }\n");
    sb.append("}");
    
    return sb.toString();
  }
  
  /**
   * Generate ComputedValue for TWO operands expression
   * @param ctx
   * @param id
   * @param child0
   * @param child1
   * @param valueType
   * @return
   * @throws ELException
   * @throws NotFoundException
   */
  protected String generateComputedValue2(ELParserContext ctx, int id, Node child0, Node child1, JClassType valueType) throws ELException, NotFoundException{
    StringBuffer sb = new StringBuffer();
    
    sb.append("new ComputedValue(" + valueType.getQualifiedSourceName() + ".class){\n");
    if (!child0.isStaticValue(ctx)){
      sb.append("  IObservableValue v0 = ");
      sb.append(child0.generateModelObservaleValue(ctx));
      sb.append(";\n");
    }
    if (!child1.isStaticValue(ctx)){
      sb.append("  IObservableValue v1 = ");
      sb.append(child1.generateModelObservaleValue(ctx));
      sb.append(";\n");
    }
    
    sb.append("  protected Object calculate(){\n");
    
    sb.append("    return ");
    if (!child0.isStaticValue(ctx)){
      sb.append("(");
      sb.append(child0.getReturnType(ctx).getQualifiedSourceName());
      sb.append(")v0.getValue()");
    }else{
      sb.append(child0.generateGetExpression(ctx));
    }
    sb.append(" "); sb.append(operators[this.id]); sb.append(" ");
    if (!child1.isStaticValue(ctx)){
      sb.append("(");
      sb.append(child0.getReturnType(ctx).getQualifiedSourceName());
      sb.append(")v1.getValue()");
    }else{
      sb.append(child1.generateGetExpression(ctx));
    }
    sb.append(";\n");

    sb.append("  }\n");
    sb.append("}");
    
    return sb.toString();
  }
}
